package com.hhh.springai_test.controller;


import com.fasterxml.jackson.annotation.JsonProperty;
import com.fasterxml.jackson.annotation.JsonPropertyDescription;
import com.hhh.springai_test.Advisor.ZhiPuVectorStore;
import com.hhh.springai_test.Client.ZhipuChatClient;
import com.hhh.springai_test.common.BaseResponse;
import com.hhh.springai_test.common.ErrorCode;
import com.hhh.springai_test.common.ResultUtils;
import com.hhh.springai_test.config.ChatConfig;
import com.hhh.springai_test.exception.BusinessException;
import jakarta.annotation.Resource;
import org.springframework.ai.chat.client.ChatClient;
import org.springframework.ai.chat.client.advisor.MessageChatMemoryAdvisor;
import org.springframework.ai.chat.client.advisor.QuestionAnswerAdvisor;
import org.springframework.ai.chat.memory.ChatMemory;
import org.springframework.ai.chat.model.ChatModel;
import org.springframework.ai.chat.model.ChatResponse;
import org.springframework.ai.document.Document;
import org.springframework.ai.reader.tika.TikaDocumentReader;
import org.springframework.ai.vectorstore.SearchRequest;
import org.springframework.ai.vectorstore.VectorStore;
import org.springframework.ai.zhipuai.ZhiPuAiChatModel;
import org.springframework.ai.zhipuai.ZhiPuAiChatOptions;
import org.springframework.ai.zhipuai.api.ZhiPuAiApi;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Qualifier;
import org.springframework.core.io.FileSystemResource;
import org.springframework.http.MediaType;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.bind.annotation.RestController;
import reactor.core.publisher.Flux;

import java.time.LocalDate;
import java.util.List;
import java.util.function.Function;

import static org.springframework.ai.chat.client.advisor.AbstractChatMemoryAdvisor.CHAT_MEMORY_RETRIEVE_SIZE_KEY;

@RestController
public class MyController {

    //为啥用这个模型呢，因为免费
    private static final String default_model = "GLM-4-Flash";

    //temperature 是一个超参数，用于控制生成文本的多样性和随机性。
    //低温度（例如：0.1 到 0.3）：模型会生成更确定、常规和一致的输出。低温度通常会使模型产生更加保守的回答，重复性较高，生成的内容更加准确、接近训练数据中的常见模式。
    //高温度（例如：0.7 到 1.0）：模型的输出会更加随机、多样、创意性强。高温度会导致生成的内容更加多样化，可能包括一些不太常见或创新性的回答，但也可能带来不太准确或不太连贯的结果。
    private static final double default_temperature = 0.95F;

    private final ZhiPuVectorStore zhiPuVectorStore;

    public MyController(ZhiPuVectorStore zhiPuVectorStore) {
        this.zhiPuVectorStore = zhiPuVectorStore;
    }


    @Resource
    private ChatConfig chatConfig;

    @Autowired
    @Qualifier("customMemory")  // 明确指定使用你自定义的 ChatMemory 实现
    private ChatMemory chatMemory;

    @Resource
    private ZhipuChatClient zhipuChatClient;

    public record Request(
            @JsonProperty(required = true)
            @JsonPropertyDescription("举报的名字是") String name) {

    }


    @GetMapping("/chat")
    public BaseResponse<String> generation(
            @RequestParam(value = "message", defaultValue = "你是谁呢") String message,
            @RequestParam(value = "model", defaultValue = "GLM-4-Flash") String model,
            @RequestParam(value = "temperature", defaultValue = "0.7") double temperature) {

        // 创建新的 ZhiPuAiChatOptions 实例，根据请求的参数动态设置
        ZhiPuAiChatOptions options = ZhiPuAiChatOptions.builder()
                .withModel(model)
                .withTemperature((float) temperature)
                .build();
        // 获取 ChatModel 实例，使用新的配置
        ChatModel chatModel = new ZhiPuAiChatModel(new ZhiPuAiApi(chatConfig.getApiKey()), options);
        ChatClient build = ChatClient.builder(chatModel).build();
        String substring = "";
        // 使用新的 ChatModel 进行对话生成
        String content = null;
        try {
            content = build.prompt()
                    .user(message)
                    .call()
                    .content();
        } catch (Exception e) {
            // 获取错误消息
            String errorMessage = e.getMessage();
            int i = errorMessage.lastIndexOf(":");
            String newString = errorMessage.substring(i + 2);
            substring = newString.substring(0, newString.length() - 3);
        }
        if(!substring.isEmpty()){
            throw new BusinessException(ErrorCode.PARAMS_ERROR,substring);
        }
        return ResultUtils.success(content);
    }

    @GetMapping("/AIchat")
    public BaseResponse<ChatResponse> AIGeneration(
            @RequestParam(value = "message", defaultValue = "你是谁呢") String message) {

        // 创建ZhiPuAiChatOptions对象，设置模型和温度
        ZhiPuAiChatOptions options = ZhiPuAiChatOptions.builder()
                .withModel(default_model)
                .withTemperature((float) default_temperature)
                .build();
        // 创建ZhiPuAiChatModel对象，传入ZhiPuAiApi和options
        ChatModel chatModel = new ZhiPuAiChatModel(new ZhiPuAiApi(chatConfig.getApiKey()), options);
        // 创建ChatClient对象，传入chatModel
        ChatClient build = ChatClient.builder(chatModel).build();
        String substring = "";
        ChatResponse chatResponse = null;
        try {
            chatResponse = build.prompt()
                    .user(message)
                    .call()
                    .chatResponse();
        } catch (Exception e) {
            // 获取异常信息
            String errorMessage = e.getMessage();
            // 获取异常信息中冒号后面的内容
            int i = errorMessage.lastIndexOf(":");
            String newString = errorMessage.substring(i + 2);
            // 去掉异常信息中的最后一个字符
            substring = newString.substring(0, newString.length() - 3);
        }
        // 如果异常信息不为空，抛出BusinessException异常
        if(!substring.isEmpty()){
            throw new BusinessException(ErrorCode.PARAMS_ERROR,substring);
        }
        // 返回成功结果
        return ResultUtils.success(chatResponse);
    }

    @GetMapping(value = "/AIGenerationEntity")
    public BaseResponse AIGenerationEntity(
            @RequestParam(value = "message", defaultValue = "你是谁呢") String message) {

        // 创建ZhiPuAiChatOptions对象，设置模型和温度
        ZhiPuAiChatOptions options = ZhiPuAiChatOptions.builder()
                .withModel(default_model)
                .withTemperature((float) default_temperature)
                .build();
        // 创建ZhiPuAiChatModel对象，传入ZhiPuAiApi和options
        ChatModel chatModel = new ZhiPuAiChatModel(new ZhiPuAiApi(chatConfig.getApiKey()), options);
        // 创建ChatClient对象，传入chatModel
        ChatClient chatClient = ChatClient.builder(chatModel).build();
        // 返回成功结果
        return chatClient.prompt()
                .user(message)
                .call()
                .entity(BaseResponse.class);
    }

    @GetMapping(value = "/AIStream",produces = MediaType.TEXT_EVENT_STREAM_VALUE)
    public Flux<String> AIStream(
            @RequestParam(value = "message", defaultValue = "你是谁呢") String message) {

        // 创建ZhiPuAiChatOptions对象，设置模型和温度
        ZhiPuAiChatOptions options = ZhiPuAiChatOptions.builder()
                .withModel(default_model)
                .withTemperature((float) default_temperature)
                .build();
        // 创建ZhiPuAiChatModel对象，传入ZhiPuAiApi和options
        ChatModel chatModel = new ZhiPuAiChatModel(new ZhiPuAiApi(chatConfig.getApiKey()), options);
        // 创建ChatClient对象，传入chatModel
        ChatClient chatClient = ChatClient.builder(chatModel).build();
        Flux<String> content = chatClient.prompt()
                .user(message)
                .stream()
                .content();
        // 返回成功结果
        return content;
    }

    // 使用GetMapping注解，指定请求路径为/AIChatResponseStream，返回类型为TEXT_EVENT_STREAM_VALUE
    @GetMapping(value = "/AIChatResponseStream",produces = MediaType.TEXT_EVENT_STREAM_VALUE)
    // 定义一个方法，返回类型为Flux<ChatResponse>，参数为String类型的message，默认值为"你是谁呢"
    public Flux<ChatResponse> AIChatResponseStream(
            @RequestParam(value = "message", defaultValue = "你是谁呢") String message) {

        // 创建ZhiPuAiChatOptions对象，设置模型和温度
        ZhiPuAiChatOptions options = ZhiPuAiChatOptions.builder()
                .withModel(default_model)
                .withTemperature((float) default_temperature)
                .build();
        // 创建ChatModel对象，传入ZhiPuAiApi和options
        ChatModel chatModel = new ZhiPuAiChatModel(new ZhiPuAiApi(chatConfig.getApiKey()), options);
        // 创建ChatClient对象，传入chatModel
        ChatClient chatClient = ChatClient.builder(chatModel).build();
        // 调用chatClient的prompt方法，传入message，返回一个Flux<ChatResponse>对象
        Flux<ChatResponse> chatResponseFlux = chatClient.prompt()
                .user(message)
                .stream()
                .chatResponse();
        // 返回Flux<ChatResponse>对象
        return chatResponseFlux;
    }

    // 使用GetMapping注解，指定请求路径为/AIChatDefaultStream，返回类型为文本流
    @GetMapping(value = "/AIChatDefaultStream",produces = MediaType.TEXT_EVENT_STREAM_VALUE)
    public Flux<String> AIChatDefaultStream(
            // 使用RequestParam注解，指定请求参数名为message，类型为String
            @RequestParam(value = "message") String message) {
        // 创建ZhiPuAiChatOptions对象，设置模型和温度
        ZhiPuAiChatOptions options = ZhiPuAiChatOptions.builder()
                .withModel(default_model)
                .withTemperature((float) default_temperature)
                .build();
        // 创建ChatModel对象，传入ZhiPuAiApi和options
        ChatModel chatModel = new ZhiPuAiChatModel(new ZhiPuAiApi(chatConfig.getApiKey()), options);
        // 创建ChatClient对象，传入chatModel，设置默认系统消息和默认顾问
        ChatClient chatClient = ChatClient.builder(chatModel).defaultSystem("你现在的身份是一个星轨会议系统的客服助手，请以友好、乐于助人且愉快的方式来回复。我希望你可以以中文的方式给我回答。这里我问你日期的话再回答，否则的话你不要回答，今天的日期是 {current_date}.")
                //.defaultAdvisors(new PromptChatMemoryAdvisor(chatMemory))
                .defaultAdvisors(new MessageChatMemoryAdvisor(chatMemory))
                .build();
        // 调用chatClient的prompt方法，设置用户消息、系统消息参数、顾问参数，返回内容流
        Flux<String> content = chatClient.prompt()
                .user(message)
                .system(s->s.param("current_date", LocalDate.now().toString()))
                .advisors(a -> a.param(CHAT_MEMORY_RETRIEVE_SIZE_KEY, 100))
                .stream()
                .content();
        // 返回内容流
        return content;
    }

    // 使用GetMapping注解，指定请求路径为/AIChatDefaultStream，返回类型为文本流
    @GetMapping(value = "/AIChatDefaultLoggingStream", produces = MediaType.TEXT_EVENT_STREAM_VALUE)
    public Flux<String> AIChatDefaultLoggingStream(@RequestParam(value = "message") String message) {
        Flux<String> content = zhipuChatClient.getZhipuChatClient().prompt()
                .user(message)
                .function("report", "举报", new Function<MyController.Request, Flux<String>>() {
                    @Override
                    public Flux<String> apply(MyController.Request request) {
                        System.out.println("举报名字是" + request.name);
                        return Flux.just("星轨");
                    }
                })
                .stream()
                .content();
        return content;
    }

    @GetMapping(value = "/AIChatRagStream", produces = MediaType.TEXT_EVENT_STREAM_VALUE)
    public Flux<String> AIChatRagStream(@RequestParam(value = "message") String message) {
        String path = "src/main/resources/static/jubao.txt";
         zhiPuVectorStore.readAndAddDocuments(path);
        Flux<String> content = zhipuChatClient.getZhipuChatClient().prompt()
                .user(message)
                .advisors(new QuestionAnswerAdvisor(zhiPuVectorStore, SearchRequest.defaults()))
                .stream()
                .content();
        return content;
    }
}
